package com.frogs.ucenter.openplatform.util;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.params.ConnRoutePNames;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.frogs.ucenter.openplatform.entity.PostObject;

public class BaseHttpsConnectUtil {
	private final static Logger log = LoggerFactory.getLogger(BaseHttpsConnectUtil.class);	

	protected static Map<String ,String> headMap= new HashMap<String,String>();
	
	static {
		headMap.put("User-Agent","Mozilla/4.0 (compatible; MSIE 7.0;)" );
		headMap.put("Accept", "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*");
	}
	
	/**
	 * 获取ssl连接
	 * @return
	 * @throws Exception
	 */
	private static ThreadSafeClientConnManager getThreadSafeClientConnManager() throws Exception{
        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
            public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
        };
        ctx.init(null, new TrustManager[] { tm }, null);
        SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("https", 443, ssf));
        ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(registry);
        return mgr;
        
    }
	
	/**
	 * 初始化HttpGet，设置heads，参数
	 * @param postObject
	 * @return
	 * @throws URISyntaxException
	 */
	private static HttpGet getHttpGetInstance (PostObject postObject) throws URISyntaxException{
		HttpGet get = new HttpGet(postObject.getUrl()); 
		//设置头部信息
		if (postObject.getHeaders() != null) {
			for (String header : postObject.getHeaders().keySet()) {
				get.addHeader(header, postObject.getHeaders().get(header));
			}
		}
		//设置提交的内容
		get.setURI(new URI(get.getURI().toString() + "?" + postObject.getContent())); 
		return get;
	}
	
	/**
	 * 初始化HttpClient，设置代理，超时时间，是否使用TSL协议
	 * @param postObject
	 * @return
	 * @throws Exception
	 */
	private static HttpClient getHttpClientInstance (PostObject postObject) throws Exception{
		HttpClient client;
		
		if(postObject.isHttps())
			client = new DefaultHttpClient(getThreadSafeClientConnManager());
		else
			client = new DefaultHttpClient();
		//设置代理
		String proxyArray[] = postObject.getProxyIpAndPort();
		if(null != proxyArray && proxyArray.length > 2){
			HttpHost proxy = new HttpHost(proxyArray[0], Integer.parseInt(proxyArray[1]));
			client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
		}
		client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,postObject.getTimeOut());  
		return client;
	}
	
	/**
	 * 
	 * @param postObject
	 * @return
	 */
	public static JSONObject get(PostObject postObject){
		JSONObject returnJson = null;
		HttpClient client = null;
		try {
			client = getHttpClientInstance(postObject);
			 
			HttpGet httpGet = getHttpGetInstance(postObject);
			
			//开始请求
			HttpResponse res = client.execute(httpGet);
			
			String strResult = EntityUtils.toString(res.getEntity(), postObject.getCharset());// 取得返回的字符串
			
			returnJson = (JSONObject) JSON.parse(strResult);
		} catch(URISyntaxException uee){
			returnJson = (JSONObject) JSON.parse("{tip:\"URI格式有误\"}");
			log.error("func[get] postObject[{}] exception[{} - {}] desc[fail]",//
					new Object[] {JSON.toJSONString(postObject) , uee.getMessage(), Arrays.deepToString(uee.getStackTrace()) });
		} catch (Exception e) {
			returnJson = (JSONObject) JSON.parse("{tip:\"连接获取数据失败\"}");
			log.error("func[get] postObject[{}] exception[{} - {}] desc[fail]",//
					new Object[] {JSON.toJSONString(postObject) , e.getMessage(), Arrays.deepToString(e.getStackTrace()) });
		} finally {
			if(client != null)
				client.getConnectionManager().shutdown();// 关闭连接 ,释放资源
		}
		return returnJson;
	}
	/**
	 * 
	 * @param postObject
	 * @return
	 */
	public static JSONObject getQqOpenid(PostObject postObject){
		JSONObject returnJson = null;
		HttpClient client = null;
		try {
			client = getHttpClientInstance(postObject);
			
			HttpGet httpGet = getHttpGetInstance(postObject);
			
			//开始请求
			HttpResponse res = client.execute(httpGet);
			
			String strResult = EntityUtils.toString(res.getEntity(), postObject.getCharset());// 取得返回的字符串
			
			strResult = strResult.replace("callback(", "").replace(");", "");
			
			returnJson = (JSONObject) JSON.parse(strResult.trim());
			
		} catch(URISyntaxException uee){
			returnJson = (JSONObject) JSON.parse("{tip:\"URI格式有误\"}");
			log.error("func[getQqOpenid] postObject[{}] exception[{} - {}] desc[fail]",//
					new Object[] {JSON.toJSONString(postObject) , uee.getMessage(), Arrays.deepToString(uee.getStackTrace()) });
		} catch (Exception e) {
			returnJson = (JSONObject) JSON.parse("{tip:\"连接获取数据失败\"}");
			log.error("func[getQqOpenid] postObject[{}] exception[{} - {}] desc[fail]",//
					new Object[] {JSON.toJSONString(postObject) , e.getMessage(), Arrays.deepToString(e.getStackTrace()) });
		} finally {
			if(client != null)
				client.getConnectionManager().shutdown();// 关闭连接 ,释放资源
		}
		return returnJson;
	}
	/**
	 * QQ联合登录返回字符串
	 * @param postObject
	 * @return
	 * access_token=F02A732D68E5B74075FD3397238419E3&expires_in=7776000&refresh_token=7901798C751513836356D704D5D8C00A
	 */
	public static String getReturnString(PostObject postObject){
		String strResult = "";
		HttpClient client = null;
		try {
			client = getHttpClientInstance(postObject);
			
			HttpGet httpGet = getHttpGetInstance(postObject);
			
			//开始请求
			HttpResponse res = client.execute(httpGet);
			
			strResult = EntityUtils.toString(res.getEntity(), postObject.getCharset());// 取得返回的字符串
		} catch(URISyntaxException uee){
			log.error("func[getReturnString] postObject[{}] exception[{} - {}] desc[fail]",//
					new Object[] {JSON.toJSONString(postObject) , uee.getMessage(), Arrays.deepToString(uee.getStackTrace()) });
		} catch (Exception e) {
			log.error("func[getReturnString] postObject[{}] exception[{} - {}] desc[fail]",//
					new Object[] {JSON.toJSONString(postObject) , e.getMessage(), Arrays.deepToString(e.getStackTrace()) });
		} finally {
			if(client != null)
				client.getConnectionManager().shutdown();// 关闭连接 ,释放资源
		}
		return strResult;
	}
	
	enum ContentTypeEnum {
		JSON("application/json"),
		XML("text/xml"),
		WWW_FORM("application/x-www-form-urlencoded"),
		MULTIPART_FORM("multipart/form-data");
		
		String type;
		
		ContentTypeEnum(String type){
	        this.type = type;
	    }

		public String getType() {
			return type;
		}

		public void setType(String type) {
			this.type = type;
		}

		@Override
		public String toString() {
			return this.type;
		}
	}
	/**
	 * 说明：
	 * 提交json：ContentType为{@link ContentTypeEnum} JSON， Content为json格式的字符串
	 * 提交xml：ContentType为{@link ContentTypeEnum} XML， Content为xml格式的字符串
	 * 提交form：ContentType为{@link ContentTypeEnum} WWW_FORM， Content为链接参数格式的字符串
	 * 
	 * 此方法暂时不支持MULTIPART_FORM 以后再实现
	 * @param postObject
	 * @return
	 * @throws Exception 
	 */
	public static JSONObject post(PostObject postObject ){
		JSONObject returnJson = null;
		HttpClient client = null;
		try {
			client = getHttpClientInstance(postObject);
			HttpPost post = getHttpPostInstance(postObject);
			//开始请求
			HttpResponse res = client.execute(post);
			String strResult = EntityUtils.toString(res.getEntity(), postObject.getCharset());// 取得返回的字符串
			returnJson = (JSONObject) JSON.parse(strResult);
		}catch(UnsupportedEncodingException uee){
			returnJson = (JSONObject) JSON.parse("{tip:\"内容编码失败\"}");
			log.error("func[post] postObject[{}] exception[{} - {}] desc[fail]",//
					new Object[] {JSON.toJSONString(postObject) , uee.getMessage(), Arrays.deepToString(uee.getStackTrace()) });
		}
		catch (Exception e) {
			returnJson = (JSONObject) JSON.parse("{tip:\"连接获取数据失败\"}");
			log.error("func[post] postObject[{}] exception[{} - {}] desc[fail]",//
					new Object[] {JSON.toJSONString(postObject) , e.getMessage(), Arrays.deepToString(e.getStackTrace()) });
		} finally {
			if(client != null)
				client.getConnectionManager().shutdown();// 关闭连接 ,释放资源
		}
		return returnJson;
	}
	/**
	 * 初始化HttpPost，设置heads，参数
	 * @param postObject
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private static HttpPost getHttpPostInstance (PostObject postObject) throws UnsupportedEncodingException{
		//设置头部信息
		HttpPost post = new HttpPost(postObject.getUrl());
		if (postObject.getHeaders() != null) {
			for (String header : postObject.getHeaders().keySet()) {
				post.addHeader(header, postObject.getHeaders().get(header));
			}
		}
		
		//设置提交的内容
		StringEntity s = new StringEntity(postObject.getContent(), postObject.getCharset());
		s.setContentEncoding(postObject.getCharset());
		s.setContentType(postObject.getContentType());
		post.setEntity(s);
		return post;
	}
}
